﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace WeManageService    //在Notifier外部操作一定要和Notifier同步数据
{
    public delegate void Notice(NoticeArgs args);
    public delegate void AutoFinish(List<int> RemoveID);

    public class NoticeArgs
    {
        public List<Plan> Plans { get; set; }
        public int State { get; set; }//state为0表示提醒即将开始的任务，
                                       //state为1表示提醒即将ddl的任务，
                            //前端根据state使用不同的界面，Plans是符合提醒条件的任务序列

        public NoticeArgs() { }
        public NoticeArgs(List<Plan> plans,int state)
        {
            Plans = plans;
            State = state;
        }
    }

    class TimerState
    {

    }

    public class Notifier
    {
        List<Plan> UnStartedPlan = new List<Plan>();
        List<Plan> UnFinishedPlan = new List<Plan>();
        List<Plan> NoticedPlan = new List<Plan>();//已经提醒过的ddl任务

        PlanDBManager dbManager = new PlanDBManager();
        Timer timer = null;

        public event Notice StartNotice;
        public event AutoFinish StartAutoFinish;
        
        public void StartTimer(string Uname)//启动定时器并且做第一次提醒
        {
            UnStartedPlan.Clear();
            UnFinishedPlan.Clear();

            var TotalPlan = dbManager.GetUndonePlan();
            TotalPlan = TotalPlan.Where(p => p.UserName == Uname).ToList<Plan>();

            if (TotalPlan.Count != 0)
            foreach (Plan plan in TotalPlan)
            {
                //if (plan.StartTime > DateTime.Now.AddDays(1)) break;//只统计当天的任务
                if (plan.StartTime > DateTime.Now) UnStartedPlan.Add(plan);
                else UnFinishedPlan.Add(plan);
            }
            UnStartedPlan.Sort((p1, p2) => { if (p1.NotifyTime < p2.NotifyTime) return -1; else if (p1.NotifyTime > p2.NotifyTime) return 1; else return 0; });
            UnFinishedPlan.Sort((p1, p2) => { if (p1.EndTime < p2.EndTime) return -1; else if (p1.EndTime > p2.EndTime) return 1; else return 0; });

            TimerState state = new TimerState();
            this.timer = new Timer(JudgeTime, state, 0, 1000);
        }

        public void JudgeTime(object obj)
        {
            Console.WriteLine("JudgeTime at" + DateTime.Now);
            List<Plan> NeedNoticePlan = new List<Plan>();
            NoticeArgs args;
            lock(this.UnStartedPlan)
            {
                lock(this.UnFinishedPlan)
                {

                    AutoFinishPlan();//到期任务自动结束

                    Plan plan = UnStartedPlan.FirstOrDefault();
                    while (plan != null && plan.NotifyTime<DateTime.Now)
                    {
                        NeedNoticePlan.Add(plan);
                        UnFinishedPlan.Add(plan);
                        UnStartedPlan.Remove(plan);
                        plan = UnStartedPlan.FirstOrDefault();
                    }
                    args = new NoticeArgs(NeedNoticePlan, 0);
                    StartNotice(args);

                    NeedNoticePlan.Clear();

                    UnFinishedPlan.Sort((p1, p2) => { if (p1.EndTime < p2.EndTime) return -1; else if (p1.EndTime > p2.EndTime) return 1; else return 0; });

                    plan = UnFinishedPlan.FirstOrDefault();
                    while(plan != null && plan.EndTime.AddHours(-1)<DateTime.Now)
                    {
                        NoticedPlan.Add(plan);
                        NeedNoticePlan.Add(plan);
                        UnFinishedPlan.Remove(plan);
                        plan = UnFinishedPlan.FirstOrDefault();
                    }
                    args = new NoticeArgs(NeedNoticePlan, 1);
                    StartNotice(args);
                }
            }
        }

        public void AutoFinishPlan()
        {
            List<int> RemoveID = new List<int>();
            lock(this.UnStartedPlan)
            {
                lock(this.UnFinishedPlan)
                {
                    NoticedPlan.Sort((p1, p2) => { if (p1.EndTime < p2.EndTime) return -1; else if (p1.EndTime > p2.EndTime) return 1; else return 0; });

                    Plan plan = UnFinishedPlan.FirstOrDefault();
                    while(plan != null && plan.EndTime<DateTime.Now)
                    {
                        UnFinishedPlan.Remove(plan);
                        RemoveID.Add(plan.PlanID);
                        plan = UnFinishedPlan.FirstOrDefault();
                    }

                    plan = NoticedPlan.FirstOrDefault();
                    while (plan != null && plan.EndTime < DateTime.Now)
                    {
                        NoticedPlan.Remove(plan);
                        RemoveID.Add(plan.PlanID);
                        plan = NoticedPlan.FirstOrDefault();
                    }

                    StartAutoFinish(RemoveID);
                    //这里需要加一个事件通知其他地方任务已经自动到期了(循环任务处理还没做)
                    UnStartedPlan.Sort((p1, p2) => { if (p1.NotifyTime < p2.NotifyTime) return -1; else if (p1.NotifyTime > p2.NotifyTime) return 1; else return 0; });
                }
            }
        }

        public void AddPlan(Plan plan)
        {
            lock(this.UnStartedPlan)
            {
                lock(this.UnFinishedPlan)
                {
                    if (plan.StartTime > DateTime.Now)
                    {
                        UnStartedPlan.Add(plan);
                        UnStartedPlan.Sort((p1, p2) => { if (p1.NotifyTime < p2.NotifyTime) return -1; else if (p1.NotifyTime > p2.NotifyTime) return 1; else return 0; });
                    }
                    else
                    {
                        UnFinishedPlan.Add(plan);
                        UnFinishedPlan.Sort((p1, p2) => { if (p1.EndTime < p2.EndTime) return -1; else if (p1.EndTime > p2.EndTime) return 1; else return 0; });
                    }
                }
            }
        }

        public void UpdatePlan(Plan plan)
        {
            lock(this.UnStartedPlan)
            {
                lock(this.UnFinishedPlan)
                {
                    bool flag = false;
                    for (int index = 0;index<UnStartedPlan.Count;index++)
                    {
                        if (UnStartedPlan[index].PlanID == plan.PlanID)
                        {
                            UnStartedPlan[index] = plan;
                            UnStartedPlan.Sort((p1, p2) => { if (p1.NotifyTime < p2.NotifyTime) return -1; else if (p1.NotifyTime > p2.NotifyTime) return 1; else return 0; });
                            flag = true;
                            break;
                        }
                    }
                    if (flag==false)
                    {
                        for (int index = 0; index < UnFinishedPlan.Count; index++)
                        {
                            if (UnFinishedPlan[index].PlanID == plan.PlanID)
                            {
                                UnFinishedPlan[index] = plan;
                                UnFinishedPlan.Sort((p1, p2) => { if (p1.EndTime < p2.EndTime) return -1; else if (p1.EndTime > p2.EndTime) return 1; else return 0; });
                                break;
                            }
                        }
                    }
                }
            }
        }

        public void ManualFinishPlan(int id)
        {
            lock(this.UnStartedPlan)
            {
                lock(this.UnFinishedPlan)
                {
                    bool flag = false;
                    for (int index = 0; index < UnStartedPlan.Count; index++)
                    {
                        if (UnStartedPlan[index].PlanID == id)
                        {
                            UnStartedPlan.RemoveAt(index);
                            flag = true;
                            break;
                        }
                    }
                    if (flag == false)
                    {
                        for (int index = 0; index < UnFinishedPlan.Count; index++)
                        {
                            if (UnFinishedPlan[index].PlanID == id)
                            {
                                UnFinishedPlan.RemoveAt(index);
                                break;
                            }
                        }
                    }
                }
            }
        }

        public void StopTimer()
        {
            timer.Dispose();
            timer = null;
        }
    }
}
